<html>

<head>
    <title>BusTub B+Tree Visualizer</title>
    <!-- jQuery -->
    <script src="https://unpkg.com/jquery@3.x.x/dist/jquery.min.js"></script>
    <!-- jQuery Terminal -->
    <script src="https://unpkg.com/jquery.terminal@2.x.x/js/jquery.terminal.min.js"></script>
    <link rel="stylesheet" href="https://unpkg.com/jquery.terminal@2.x.x/css/jquery.terminal.min.css" />
    <!-- prismjs  -->
    <link rel="stylesheet" href="https://unpkg.com/prismjs@1.x.x/themes/prism.min.css" />
    <link rel="stylesheet" href="https://unpkg.com/terminal-prism@0.3.x/css/prism.css" />
    <script src="https://unpkg.com/prismjs@1.x.x/prism.js"></script>
    <script src="https://unpkg.com/prismjs@1.x.x/components/prism-sql.min.js"></script>
    <script src="https://unpkg.com/jquery.terminal@2.x.x/js/prism.js"></script>
    <!-- CJK characters -->
    <script src="https://cdn.jsdelivr.net/gh/jcubic/static/js/wcwidth.js"></script>
    <!-- Roboto Mono -->
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Source+Code+Pro:wght@400;700&display=swap" rel="stylesheet">

    <!-- Preview -->
    <meta property="og:site_name" content="CMU 15-445/645" />
    <meta property="og:type" content="website" />
    <meta property="og:title" content="BusTub B+Tree Visualizer" />
    <meta property="og:url" content="https://15445.courses.cs.cmu.edu" />
    <meta property="og:description" content="Online visualization tool for BusTub's B+Tree project" />
    <meta property="og:image" content="https://15445.courses.cs.cmu.edu/fall2022/images/bustub-shell.png" />
    <meta name="twitter:card" content="summary_large_image">
    <meta name="twitter:site" content="@CMUDB">
    <meta name="twitter:creator" content="@CMUDB">
    <meta name="twitter:domain" content=".">
    <meta property="twitter:label1" content="Semester?" />
    <meta property="twitter:data1" content="Spring 2025" />
    <meta property="twitter:label1" content="Relational?" />
    <meta property="twitter:data1" content="Hell Yes" />

    <!-- GraphViz -->
    <script src="https://unpkg.com/viz.js@2.x.x/viz.js"></script>
    <script src="https://unpkg.com/viz.js@2.x.x/full.render.js"></script>
    <!-- Pan Zoom -->
    <script src="https://unpkg.com/svg-pan-zoom@3.6.1/dist/svg-pan-zoom.min.js"></script>
</head>

<body>
</body>

<style>
    .terminal {
        --color: black;
        --background: white;
        --link-color: darkblue;
        --size: 1.2;
        --font: "Source Code Pro", monospace;
    }

    .terminal::after {
        content: "";
        background-image: url("bustub.svg");
        opacity: 0.02;
        top: -50%;
        left: -50%;
        width: 200%;
        height: 200%;
        position: absolute;
        z-index: -1;
        transform: rotate(-30deg);
    }

    table,
    tr,
    td,
    tbody,
    thead,
    div {
        font-size: calc(var(--size, 1)*(12px/var(--pixel-density, 1)));
        white-space: pre;
    }

    .svg-wrapper {
        width: 80%;
        overflow-x: hidden;
        background-color: white;
        border: 1px solid grey;
    }
</style>

<script src="bustub-wasm-bpt-printer.js"></script>

<script type="text/javascript">
    const BUSTUB_PUBLIC_VERSION_VAR = "${BUSTUB_PUBLIC_VERSION}"
    const BUSTUB_PRIVATE_VERSION_VAR = "${BUSTUB_PRIVATE_VERSION}"
    const BUSTUB_BUILD_TIME_VAR = "${BUSTUB_BUILD_TIME}"
    const viz = new Viz()

    Module['onRuntimeInitialized'] = function () {
        const initialize = Module.cwrap('BusTubInit', 'number', ['number', 'number'])
        const executeQuery = Module.cwrap('BusTubApplyCommand', 'number', ['string', 'number', 'number'])
        window.executeQuery = (x) => {
            const bufferSize = 64 * 1024
            const ptrOutput = Module._malloc(bufferSize)
            Module.stringToUTF8("", ptrOutput, bufferSize)
            const retCode = executeQuery(x, ptrOutput, bufferSize)
            output = Module.UTF8ToString(ptrOutput)
            Module._free(ptrOutput)
            return [retCode, output]
        }
        window.initialize = initialize
    }

    const helpMessage =
        "i <k>  -- Insert <k> (int64_t) as both key and value).\n" +
        "d <k>  -- Delete key <k> and its associated value.\n"


    function preventScroll(e) {
        e.preventDefault();
        e.stopPropagation();

        return false;
    }

    $(document).ready(() => {
        var initialized = false
        var svgid = 0
        var term = $('body').terminal(function (line) {
            if (line == "\\clear") {
                this.clear()
            } else if (line == "?") {
                this.echo(helpMessage)
            } else {
                if (!window.initialize) {
                    this.echo("BusTub shell is still initializing, please wait.")
                } else if (!initialized) {
                    const [x, y] = line.split(" ")
                    const [px, py] = [parseInt(x), parseInt(y)]
                    if (px >= 2 && py >= 3) {
                        initialize(px, py)
                        this.echo(`leaf_max_size=${px}, internal_max_size=${py}`)
                        initialized = true
                    }
                } else {
                    const [retCode, result] = executeQuery(line)
                    if (retCode == 0) {
                        viz.renderSVGElement(result).then((svgXml) => {
                            id = `bustub-svg-${svgid}`
                            svgXml.id = id
                            svgid += 1
                            const div = document.createElement("div")
                            div.className = "svg-wrapper"
                            div.appendChild(svgXml)
                            this.echo(div, { raw: true })
                            svgPanZoom(`#${id}`)
                            $(`#${id}`).width("100%")
                            document.querySelector(`#${id}`).addEventListener('wheel', preventScroll, { passive: false });
                            this.echo("")
                        })
                    }
                    if (retCode == 1) {
                        this.echo("something went wrong.")
                    }
                    if (retCode == 2) {
                        this.echo("output truncated due to output limit.")
                    }
                }
            }
        }, {
            greetings: `[[@;;;;bustub.svg]]`,
            prompt: () => initialized ? "[[b;;]printer> ]" : "leaf_max_size and internal_max_size? (e.g., 3 3) "
        })
        term.echo(`<hr><h1>BusTub B+Tree Visualizer</h1>`, { raw: true })
        term.echo(`
[[b;;]Solution Version:] ${BUSTUB_PRIVATE_VERSION_VAR} . [[b;;]BusTub Version:] ${BUSTUB_PUBLIC_VERSION_VAR} . [[b;;]Built Date:] ${BUSTUB_BUILD_TIME_VAR}

BusTub is a relational database management system built at Carnegie Mellon University for the Introduction to Database Systems (15-445/645) course. This system was developed for educational purposes and should not be used in production environments. &#91;[[!;;;;https://github.com/cmu-db/bustub]BusTub on GitHub]&#93; &#91;[[!;;;;https://15445.courses.cs.cmu.edu/]Course Website]&#93; &#91;[[!;;;;https://github.com/cmu-db/bustub/issues/new]Report Bugs]&#93;

${helpMessage}
`)
    })
</script>

<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-52525161-8"></script>
<script>
    window.dataLayer = window.dataLayer || [];
    function gtag() { dataLayer.push(arguments); }
    gtag('js', new Date());

    gtag('config', 'UA-52525161-8');
</script>

</html>